home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue40 / COMCorn / UtilObjs.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-11-10  |  5.6 KB  |  220 lines

  1. unit UtilObjs;
  2.  
  3. interface
  4.  
  5. uses Windows, Classes, ShlObj, ActiveX, ComObj;
  6.  
  7. type
  8.   // Class which contains the IEnumIDList implementation for the
  9.   // main TComNameExt class.  This implementation is aggregated to
  10.   // TComNameExt using the implements directive.
  11.   TComServerList = class(TList) { IEnumIDList }
  12.   private
  13.     FCurrent: Integer;
  14.     FOwner: TComObject;
  15.     FShellMalloc: IMalloc;
  16.   public
  17.     constructor Create(Owner: TComObject);
  18.     procedure AddGuid(const Item: TGUID); virtual;
  19.     procedure Clear; override;
  20.     { IEnumIDList methods }
  21.     function Next(celt: ULONG; out rgelt: PItemIDList;
  22.       var pceltFetched: ULONG): HResult; stdcall;
  23.     function Skip(celt: ULONG): HResult; stdcall;
  24.     function Reset: HResult; stdcall;
  25.     function Clone(out ppenum: IEnumIDList): HResult; stdcall;
  26.   end;
  27.  
  28.   // Base class which implements IUnknown for classes that are dispensed
  29.   // by TComNameExt when multiple instances of an interface are required.
  30.   // For example, IShellView, IContextMenu, and IExtractIcon are
  31.   // implemented using a derivative of this class.
  32.   TMultiAggregatedObject = class(TInterfacedObject, IUnknown)
  33.   private
  34.     FController: TComObject;
  35.   protected
  36.     { IUnknown }
  37.     function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
  38.   public
  39.     constructor Create(Controller: TComObject); virtual;
  40.     destructor Destroy; override;
  41.     property Controller: TComObject read FController;
  42.   end;
  43.  
  44.   // TSHItemID-type record which is specific to this implementation
  45.   PServInfo = ^TServInfo;
  46.   TServInfo = record  { TSHItemID }
  47.     Size: Word;
  48.     CLSID: TGUID;
  49.   end;
  50.  
  51. // Helper functions to create and delete reg keys & values
  52.  
  53. procedure CreateRegKeyEx(const Key, ValueName: string; Value: PChar;
  54.   Kind, Size: DWORD; RootKey: HKEY);
  55.  
  56. procedure DeleteRegValue(const Key, ValueName: string; RootKey: HKEY);
  57.  
  58. implementation
  59.  
  60. uses SysUtils;
  61.  
  62. procedure CreateRegKeyEx(const Key, ValueName: string; Value: PChar;
  63.   Kind, Size: DWORD; RootKey: HKEY);
  64. var
  65.   Handle: HKey;
  66.   Status, Disposition: Integer;
  67. begin
  68.   Status := RegCreateKeyEx(RootKey, PChar(Key), 0, '',
  69.     REG_OPTION_NON_VOLATILE, KEY_READ or KEY_WRITE or KEY_SET_VALUE, nil,
  70.       Handle, @Disposition);
  71.   if Status = 0 then
  72.   begin
  73.     Status := RegSetValueEx(Handle, PChar(ValueName), 0, Kind, Value, Size);
  74.     RegCloseKey(Handle);
  75.   end;
  76.   if Status <> 0 then raise EWin32Error.Create(SysErrorMessage(Status));
  77. end;
  78.  
  79. procedure DeleteRegValue(const Key, ValueName: string; RootKey: HKEY);
  80. var
  81.   Handle: HKEY;
  82.   Status: Integer;
  83. begin
  84.   Status := RegOpenKey(RootKey, PChar(Key), Handle);
  85.   if Status = 0 then
  86.   begin
  87.     Status := RegDeleteValue(Handle, PChar(ValueName));
  88.     RegCloseKey(Handle);
  89.   end;
  90.   if Status <> 0 then raise EWin32Error.Create(SysErrorMessage(Status));
  91. end;
  92.  
  93. { TComServerList }
  94.  
  95. constructor TComServerList.Create(Owner: TComObject);
  96. begin
  97.   FOwner := Owner;
  98.   inherited Create;
  99.   OleCheck(SHGetMalloc(FShellMalloc));
  100. end;
  101.  
  102. procedure TComServerList.AddGuid(const Item: TGUID);
  103. var
  104.   Guid: PGUID;
  105. begin
  106.   GetMem(Guid, SizeOf(TServInfo));
  107.   Guid^ := Item;
  108.   Add(Guid);
  109. end;
  110.  
  111. procedure TComServerList.Clear;
  112. var
  113.   I: Integer;
  114.   Item: Pointer;
  115. begin
  116.   for I := 0 to Count - 1 do
  117.   begin
  118.     Item := Items[I];
  119.     if Item <> nil then FreeMem(Item);
  120.   end;
  121.   inherited Clear;
  122. end;
  123.  
  124. { TComServerList.IEnumIDList }
  125.  
  126. function TComServerList.Clone(out ppenum: IEnumIDList): HResult;
  127. begin
  128.   Result := E_NOTIMPL;
  129. end;
  130.  
  131. function TComServerList.Next(celt: ULONG; out rgelt: PItemIDList;
  132.   var pceltFetched: ULONG): HResult;
  133. var
  134.   NewList: PServInfo;
  135.   IDPtr: ^PItemIDList;
  136. begin
  137.   try
  138.     rgelt := nil;
  139.     if @pceltFetched <> nil then pceltFetched := 0
  140.     // pceltFetched can only be nil when celt is 1
  141.     else if celt > 1 then
  142.     begin
  143.       Result := E_POINTER;
  144.       Exit;
  145.     end;
  146.     // Already at the end of the enumeration
  147.     if FCurrent = Count then
  148.     begin
  149.       Result := S_FALSE;
  150.       Exit;
  151.     end;
  152.     IDPtr := @rgelt;  // Keep pointer to walk array
  153.     // Iterate through array, assigning a newly allocated record to each element
  154.     while (celt > 0) and (FCurrent < Count) do
  155.     begin
  156.       NewList := FShellMalloc.Alloc(SizeOf(TServInfo));
  157.       NewList.Size := SizeOf(TServInfo);
  158.       NewList.CLSID := PGUID(List[FCurrent])^;
  159.       IDPtr^ := PItemIDList(NewList);
  160.       Dec(celt);
  161.       Inc(FCurrent);
  162.       Inc(IDPtr);
  163.       if @pceltFetched <> nil then Inc(pceltFetched);
  164.     end;
  165.     Result := S_OK;
  166.   except
  167.     on E: TObject do
  168.       Result := FOwner.SafeCallException(E, ExceptAddr);
  169.   end;
  170. end;
  171.  
  172. function TComServerList.Reset: HResult;
  173. begin
  174.   Result := S_OK;
  175.   FCurrent := 0;
  176. end;
  177.  
  178. function TComServerList.Skip(celt: ULONG): HResult;
  179. begin
  180.   Result := S_OK;
  181.   try
  182.     Inc(FCurrent, celt);
  183.     if FCurrent >= Count then FCurrent := Count - 1;
  184.   except
  185.     on E: TObject do
  186.       Result := FOwner.SafeCallException(E, ExceptAddr);
  187.   end;
  188. end;
  189.  
  190. { TMultiAggregatedObject }
  191.  
  192. constructor TMultiAggregatedObject.Create(Controller: TComObject);
  193. begin
  194.   FController := Controller;
  195.   inherited Create;
  196.   (FController as IUnknown)._AddRef;
  197. end;
  198.  
  199. destructor TMultiAggregatedObject.Destroy;
  200. begin
  201.   (FController as IUnknown)._Release;
  202.   inherited Destroy;
  203. end;
  204.  
  205. { TMultiAggregatedObject.IUnknown }
  206.  
  207. function TMultiAggregatedObject.QueryInterface(const IID: TGUID;
  208.   out Obj): HResult;
  209. begin
  210.   try
  211.     Result := inherited QueryInterface(IID, Obj);
  212.     if Result <> S_OK then
  213.       Result := (FController as IUnknown).QueryInterface(IID, Obj);
  214.   except
  215.     Result := E_UNEXPECTED;
  216.   end;
  217. end;
  218.  
  219. end.
  220.